package ipaintplugin.editors;

import ipaintplugin.actions.BaseToolAction;
import ipaintplugin.objects.Figure;
import ipaintplugin.objects.FigureManager;
import ipaintplugin.objects.Oval;
import ipaintplugin.objects.Rectangle;

import java.util.Vector;

import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Composite;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class Document extends Composite implements PaintListener,
		MouseListener, MouseMoveListener, Cloneable {

	private Vector<Figure> figures = new Vector<Figure>();
	private IDrawChangeListener changeListener = null;

	private BaseToolAction action;

	private MouseEvent currentMouseDown = null;
	private MouseEvent currentMousePos = null;

	public Document(Composite parent, int style) {
		super(parent, style);
		setBackground(new Color(null, 255, 255, 255));
		addPaintListener(this);
		addMouseListener(this);
		addMouseMoveListener(this);
	}
	
	public void setDrawChangeListener(IDrawChangeListener l) {
		changeListener = l;
	}

	public Vector<Figure> getFiguresClone() {
		return (Vector<Figure>)figures.clone();
	}
	
	public Vector<Figure> getFigures() {
		return figures;
	}
	
	public void setFigures(Vector<Figure> f) {
		figures = f;
		redraw();
	}
	
	public int getFigureCount() {
		return figures.size();
	}

	public void addFigure(Figure fig) {
		figures.add(fig);
	}

	public Figure getFigure(int index) {
		if (index < 0 || index >= figures.size())
			return null;
		return figures.get(index);
	}

	public void removeFigure(Figure fig) {
		figures.remove(fig);
	}

	public void toXML(org.w3c.dom.Document doc) {

		Element el = doc.createElement("document");

		el.setAttribute("width", String.valueOf(getBounds().width));
		el.setAttribute("height", String.valueOf(getBounds().height));

		doc.appendChild(el);

		for (Figure f : figures)
			f.toXML(doc, el);
	}

	public void fromXML(Element el) {
		// FIXME meter dinamico
		figures.clear();
		setBounds(0, 0, Integer.parseInt(el.getAttributes().getNamedItem(
				"width").getNodeValue()), Integer.parseInt(el.getAttributes()
				.getNamedItem("height").getNodeValue()));

		NodeList nl = el.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node child = nl.item(i);
			Figure f = FigureManager.getInstance()
					.getInstanceFromXMLNode(child);
			if (f != null)
				figures.add(f);
		}
	}

	public void setAction(BaseToolAction action) {
		this.action = action;
	}

	@Override
	public void paintControl(PaintEvent e) {
		for (Figure f : figures) {
			f.draw(e.gc);
		}

		if (action != null && currentMouseDown != null
				&& currentMousePos != null) {
			Figure fig = action.getFigureInstance(currentMouseDown,
					currentMousePos);
			fig.draw(e.gc);
		}
	}

	@Override
	public void mouseMove(MouseEvent e) {
		if (currentMouseDown != null)
			currentMousePos = e;

		redraw();
		// System.out.println("MouseMove " + e.x + " " + e.y);
	}

	@Override
	public void mouseDoubleClick(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseDown(MouseEvent e) {
		if (currentMouseDown == null)
			currentMouseDown = e;

		redraw();

		System.out.println("MouseDown " + e.x + " " + e.y);
	}

	@Override
	public void mouseUp(MouseEvent e) {

		if (action != null) {
			if(changeListener!=null)
				changeListener.change(this);
			
			figures.add(action.getFigureInstance(currentMouseDown, e));
		}
		currentMousePos = null;
		currentMouseDown = null;

		redraw();
		System.out.println("MouseUp " + e.x + " " + e.y);
	}
	
	public Object clone() {
		
		Document doc = new Document(this.getParent(), this.getStyle());
		doc.setDrawChangeListener(changeListener);
		doc.setVisible(false);
		doc.action = null;
		doc.figures.addAll(figures);
		return doc;
	}

}
